package com.yy.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yy.constant.EsConstant;
import com.yy.dto.PageDTO;
import com.yy.ex.BusinessException;
import com.yy.model.ProdEs;
import com.yy.service.SearchService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;

/**
 * 描述: []
 * 作者: yy
 */
@Service
public class SearchServiceImpl  implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 根据标签来搜索商品
     * 1.tagId match
     * 2.分页
     *
     * @param tagId
     * @param pageDTO
     * @return
     */
    @Override
    public Page<ProdEs> searchProdEsByTagId(Long tagId, PageDTO pageDTO) {
        // 分页需要 当前页 每页条数 总条数 当前页的集合
        Page<ProdEs> prodEsPage = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());

        SearchRequest searchRequest = new SearchRequest(EsConstant.PROD_ES_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        MatchQueryBuilder query = QueryBuilders.matchQuery("tagList", tagId);
        searchSourceBuilder.query(query);
        searchSourceBuilder.from((pageDTO.getCurrent() - 1) * pageDTO.getSize()); // es offset,size  limit
        searchSourceBuilder.size(pageDTO.getSize());

        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SearchHits searchHits = searchResponse.getHits();
        // 总条数
        long totalCount = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        ArrayList<ProdEs> prodEsArrayList = new ArrayList<>(hits.length);
        for (SearchHit hit : hits) {
            String prodEsStr = hit.getSourceAsString();
            ProdEs prodEs = JSON.parseObject(prodEsStr, ProdEs.class);
            prodEsArrayList.add(prodEs);
        }
        prodEsPage.setTotal(totalCount);
        prodEsPage.setRecords(prodEsArrayList);
        return prodEsPage;
    }

    /**
     * 根据关键字来搜索商品
     * 1.名字match
     * 2.排序
     * 3.分页
     * 4.高亮
     *
     * @param prodName
     * @param sort
     * @param pageDTO
     * @return
     */
    @Override
    public Page<ProdEs> searchByKeywords(String prodName, Integer sort, PageDTO pageDTO) {
        Page<ProdEs> prodEsPage = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
        SearchRequest searchRequest = new SearchRequest(EsConstant.PROD_ES_INDEX);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder query = QueryBuilders.matchQuery("prodName", prodName);
        searchSourceBuilder.query(query);
        searchSourceBuilder.from((pageDTO.getCurrent() - 1) * pageDTO.getSize()); // es offset,size  limit
        searchSourceBuilder.size(pageDTO.getSize());
        searchSourceBuilder.sort(mySort(sort));
        HighlightBuilder high = new HighlightBuilder();
        high.field("prodName");
        high.preTags("<span style='color:red'>");
        high.postTags("</span>");
        searchSourceBuilder.highlighter(high);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits searchHits = searchResponse.getHits();
        long totalCount = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        ArrayList<ProdEs> prodEsArrayList = new ArrayList<>(hits.length);
        for (SearchHit hit : hits) {
            // 拿原始数据
            String prodEsStr = hit.getSourceAsString();
            ProdEs prodEs = JSON.parseObject(prodEsStr, ProdEs.class);
            // 拿高亮数据
            HighlightField highlightField = hit.getHighlightFields().get("prodName");
            Text[] fragments = highlightField.fragments();
            StringBuilder sb = new StringBuilder();
            for (Text fragment : fragments) {
                sb.append(fragment.toString());
            }
            prodEs.setProdName(sb.toString());
            prodEsArrayList.add(prodEs);
        }
        prodEsPage.setTotal(totalCount);
        prodEsPage.setRecords(prodEsArrayList);
        return prodEsPage;
    }

    private SortBuilder<?> mySort(Integer sort) {
        switch (sort) {
            case 0:
                // 综合 好评率排序
                return SortBuilders.fieldSort("positiveRating").order(SortOrder.DESC);
            case 1:
                // 销量
                return SortBuilders.fieldSort("soldNum").order(SortOrder.DESC);
            case 2:
                // 价格
                return SortBuilders.fieldSort("price").order(SortOrder.ASC);
            default:
                throw new BusinessException("排序方式不允许");
        }
    }
}
